<template>
    <div class="hello">
        <h3>Partial Pick Record 与Readonly</h3>
        <h3>proxy 与 reflect</h3>
    </div>
</template>

<script  lang="ts" >
    import { defineComponent } from 'vue'

    export default defineComponent({
            name: 'HelloWorld',
            props: {
                msg: String
            },
            setup(props,context){ // setup 不允许前面加async
                let str:string = "string"

                interface Person {
                    name:string
                    age:number
                    text:string
                }

                const logSuccess =function<T extends {}>(obj:T,key:keyof T) {  // T extends {}
                    // return proxyfunc(obj,key)
                    return new Proxy(obj,{
                        //有人修改p的某个属性、或给p追加某个属性时调用
                        set(target,propName,value,receiver){// 修改 与 添加属性set都能监测
                            console.log(`有人修改了p身上的propName属性，我要去更新界面了！`,propName)
                            return Reflect.set(target,propName,value,receiver)// 设置什么对象的什么属性为什么值
                        },

                        //有人读取p的某个属性时调用
                        get(target,propName,value){
                            console.log(`有人读取了p身上的propName属性，我要去更新界面了！`,propName)
                            return Reflect.get(target,propName,value)// 获取什么对象的什么属性
                        },
                    })
                }
                // function proxyfunc(obj:any,key:any){
                //     return new Proxy(obj,{
                //         //有人修改p的某个属性、或给p追加某个属性时调用
                //         set(target,propName,value,receiver){// 修改 与 添加属性set都能监测
                //             console.log(`有人修改了p身上的propName属性，我要去更新界面了！`,propName)
                //             return Reflect.set(target,propName,value,receiver)// 设置什么对象的什么属性为什么值
                //         },
                //
                //         //有人读取p的某个属性时调用
                //         get(target,propName,value){
                //             console.log(`有人读取了p身上的propName属性，我要去更新界面了！`,propName)
                //             return Reflect.get(target,propName,value)// 获取什么对象的什么属性
                //         },
                //     })
                // }
                let p:Person = {
                    name:"zs",
                    age:20,
                    text:"text"
                }

                let Proxyp = logSuccess(p,"name")
                Proxyp.name = "wf"
                console.log(Proxyp.name);


                // 几个常用的工具类
                // 1:Partial => 所有属性变成可选
                interface PropsPartial{
                    id:number,
                    name:string,
                    age:number
                }
                type PartialProps = Partial<PropsPartial>
                // 转变后
                // type PartialProps = {
                //     id?: number | undefined;
                //     name?: string | undefined;
                // }
                let instanceOne:PartialProps = {}

                // 源码
                // type Partial<T> = {
                //     [P in keyof T]?: T[P]; // in用来遍历类似 for in,  keyof T 就是所有属性
                // };

                // 2:Readonly => 所有属性变成只读
                interface PropsReadonly{
                    id:number,
                    name:string
                }
                type ReadonlyProps = Readonly<PropsReadonly>
                let instanceOne2 : ReadonlyProps = {id:1,name:'xxx'}
                // 转变后
              /*  type ReadonlyProps = {
                    readonly id: number;
                    readonly name: string;
                }*/

                // instanceOne2.name='w3f'  //会报错

                //3 Pick<type,key> 从type中选择一组属性 来构造新类型
                //两个变量表示：1）表示谁的属性 2）表示选择哪一个属性，此属性只能是前面第一个变量传入的类型变量中的属性
                interface PickProps{
                    id:number,
                    name:string,
                    age:number
                }
                type AfterPickProps = Pick<PickProps,'id'|'age'>  //这表示 构造出来的新类型PickProps 只有id age两个属性类型
                let instanceOne3 : AfterPickProps = {id:1,age:20}

                //4 Record<keys,type> 构造一个对象类型，属性键为keys(哪些键),属性类型为type(键值哪些类型)
                //两个变量表示：1）表示对象有哪些属性 2）表示对象属性的类型
                type RecordObj = Record<'a'|'b'|'c',string>  //此处表示 此类型变量有a b c三个键，并且三个的属性值都是string类型
                let obj :RecordObj = {
                    a:'1',
                    b:'2',
                    c:'3'
                }
                // 等价
                // type RecordObj = {
                //     a: string;
                //     b: string;
                //     c: string;
                // }

                return {
                    str
                }
            }
        }
    )
</script>

<style scoped>

</style>
